package gridmath;

import preprocessing.WindowingSystem;
import statistics.SignificanceHelper;
import datastructures.UserParameters;

public class NeededCaseCalculator extends CaseMatrixBase {
	
	private final int Cases;
	private SignificanceHelper significance;
	
	public NeededCaseCalculator ( UserParameters userparams, WindowingSystem windowmaker, SignificanceHelper significanceHelper) {
		super(windowmaker, userparams.getMaxorder());
		Cases = userparams.getNumber_of_cases();
		significance = significanceHelper;
		specialTypeOfOperation = MatrixOperations.calculateNeededCases;
		specialTypeOfOperand = MatrixOperations.calculateExpectedCases;
	}

	public double doOperation (double operand) {
		double[][] expectedCases = new double[2][2];
		int[][] observedCases = new int[2][2];
		
		double pval = 1;
		int delta_case = 1;
		while ( pval > significance.getCaseOnlyThreshold(currentDimension) && allIsWell(observedCases) ) {
			
			switch(currentDimension) {
				case 1:
					expectedCases = windowMaker.getExpectedCases(new int[] {i}, Cases);
					observedCases[1][1] = (int) Math.round( expectedCases[1][1] + delta_case );
					observedCases[1][0] = (int) Math.round( expectedCases[1][0] - delta_case );
					if ( allIsWell(observedCases) )
						pval = significance.TestCasesOnly(currentDimension, observedCases);
					break;
					
				default:
					expectedCases = windowMaker.getExpectedCases(new int[] {i, j}, Cases);
					observedCases[1][1] = (int) Math.round( expectedCases[1][1] + delta_case );
					observedCases[1][0] = (int) Math.round( expectedCases[1][0] - delta_case );
					observedCases[0][1] = (int) Math.round( expectedCases[0][1] - delta_case );
					observedCases[0][0] = (int) Math.round( expectedCases[0][0] + delta_case );
					if ( allIsWell(observedCases) )
						pval = significance.TestCasesOnly( currentDimension, observedCases );
					break;			
			}
			
			delta_case += 1;
			
		}
		
		if ( !allIsWell(observedCases) ) {
			observedCases[1][1] = Cases + 1;
			observedCases[1][0] = 0;
			observedCases[0][1] = 0;
			observedCases[0][0] = 0;
		}
		
		return observedCases[1][1];
			
	}
	
	private boolean allIsWell( int[][] observedCases ) {
		if ( 	
				observedCases[1][1] >=0    
				&& observedCases[1][0] >=0    
				&& observedCases[0][1] >=0 
				&& observedCases[0][0] >=0 
			)
			return true;
		else
			return false;
		
	}

}
